use serde::{Serialize, Deserialize};
use sqlx::Row;

use crate::error::AppErr;

use super::get_pool;


#[derive(Debug, Serialize, Deserialize)]
pub struct JtPos {
    pub p1: f32,
    pub p2: f32,
    pub p3: f32,
    pub p4: f32,
    pub p5: f32,
    pub p6: f32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct TlPos {
    pub x: f32,
    pub y: f32,
    pub z: f32,
    pub rx: f32,
    pub ry: f32,
    pub rz: f32,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct NamedPos {
    pub name: String,
    pub jt: JtPos,
    pub tl: TlPos,
}

pub const SQL_NAMED_POS_CREATE: &'static str = r#"
    CREATE TABLE IF NOT EXISTS tb_named_pos (
        id INTEGER PRIMARY KEY AUTOINCREMENT, 
        name TEXT UNIQUE NOT NULL, 
        p1 REAL NOT NULL, 
        p2 REAL NOT NULL, 
        p3 REAL NOT NULL, 
        p4 REAL NOT NULL, 
        p5 REAL NOT NULL, 
        p6 REAL NOT NULL, 
        x REAL NOT NULL, 
        y REAL NOT NULL, 
        z REAL NOT NULL, 
        rx REAL NOT NULL, 
        ry REAL NOT NULL, 
        rz REAL NOT NULL
    )
"#;

#[tauri::command]
pub async fn save_named_pos(pos: NamedPos) -> Result<(), AppErr> {
    sqlx::query(r#"
        INSERT OR REPLACE INTO tb_named_pos(
            name, p1, p2, p3, p4, p5, p6, x, y, z, rx, ry, rz
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
    "#)
    .bind(pos.name)
    .bind(pos.jt.p1).bind(pos.jt.p2).bind(pos.jt.p3)
    .bind(pos.jt.p4).bind(pos.jt.p5).bind(pos.jt.p6)
    .bind(pos.tl.x).bind(pos.tl.y).bind(pos.tl.z)
    .bind(pos.tl.rx).bind(pos.tl.ry).bind(pos.tl.rz)
    .execute( get_pool() )
    .await?;
    
    Ok(())
}

#[tauri::command]
pub async fn del_named_pos(name: String) -> Result<(), AppErr> {

    sqlx::query(r#"
        DELETE FROM tb_named_pos WHERE name = ?
    "#)
    .bind(name)
    .execute( get_pool() )
    .await?;

    Ok(())
}

#[tauri::command]
pub async fn get_names_pos() -> Result<Vec<NamedPos>, AppErr > {

    let pos: Vec<NamedPos> = sqlx::query(r#"
        SELECT name, p1, p2, p3, p4, p5, p6, x, y, z, rx, ry, rz 
        FROM tb_named_pos    
    "#)
    .fetch_all( get_pool() )
    .await?
    .iter()
    .map(|row| {
        NamedPos {
            name: row.get(0),
            jt: JtPos { p1: row.get(1), p2: row.get(2), p3: row.get(3), p4: row.get(4), p5: row.get(5), p6: row.get(6) },
            tl: TlPos { x: row.get(7), y: row.get(8), z: row.get(9), rx: row.get(10), ry: row.get(11), rz: row.get(12) }
        }
    }).collect();

    Ok(pos)
}

